export default {
    //用于记录内部变量
    prop: {
        _areaFeatures: [],
        _specialFeatures: [],
        _heightForJudgmentAC: [],
        _selectedGra: null
    },

    startup(param) {
        const self = this;
        require([
            "esri/tasks/QueryTask",
            "esri/tasks/support/Query",
            "esri/geometry/geometryEngine"
        ], function (QueryTask, Query, geometryEngine) {
            // 存储所需ArcGIS类
            self.prop.QueryTask = QueryTask;
            self.prop.Query = Query;
            self.prop.geometryEngine = geometryEngine;

            // 展示的图层和容器
            self.prop._graphicsLayer = param.graphicsLayer;
            self.prop._webScene = param.webScene;
            self.prop._view = param.view;

            self.prop._areaServerUrl = param.areaServerUrl;// 控制面的服务地址
            self.prop._buildingAreaServerUrl = param.buildingAreaServerUrl;// 建筑物的投影面的服务地址

            self.prop._buildingSceneLayerTitle = param.buildingSceneLayerTitle;// 建筑物的图层名称
            self.prop._field = param.field;

            // 对部分函数做this对象绑定处理，方便后续调用this取值
            self.renderBuildingCheckBox = self.renderBuildingCheckBox.bind(self);
            self.checkWarningBuilding = self.checkWarningBuilding.bind(self);
            self.queryBuildings = self.queryBuildings.bind(self);
            self.highlightWarningBuilding = self.highlightWarningBuilding.bind(self);
            self.resetBuildingRender = self.resetBuildingRender.bind(self);
            self.setHeightToIpt = self.setHeightToIpt.bind(self);
            self.changeBuildingHeight = self.changeBuildingHeight.bind(self);
            self.gltfDataReady = self.gltfDataReady.bind(self);
            self.bindHandle = self.bindHandle.bind(self);

            window.__gltfDataReady = self.gltfDataReady;

            // 绑定按钮响应等操作
            self.bindHandle();

            // 渲染控高盒子
            self.renderBuildingCheckBox();
        });
    },

    bindHandle() {
        const self = this;

        document.getElementById("checkSwitchBtn").addEventListener("change", event => {
            if (event.currentTarget.checked) {
                self.checkWarningBuilding();
            } else {
                self.resetBuildingRender();
            }
        });

        document.getElementById("attrHeightIpt").addEventListener("change", self.changeBuildingHeight);

        self.prop._view.on("click", self.setHeightToIpt);
    },

    renderBuildingCheckBox() {
        const self = this;
        const field = self.prop._field;
        const queryTask = new self.prop.QueryTask({
            url: self.prop._areaServerUrl
        });
        const query = new self.prop.Query();
        query.where = "1=1";
        query.returnGeometry = true;
        query.outFields = ["objectid", field];
        query.outSpatialReference = self.prop._view.spatialReference;
        queryTask.execute(query).then(function (res) {
            const features = res.features;
            self.prop._areaFeatures = res.features;

            for (let i = 0; i < features.length; i++) {
                let the_size = Number(features[i].attributes[field]);
                features[i].symbol = {
                    type: "polygon-3d",
                    symbolLayers: [{
                        type: "extrude",
                        size: the_size,
                        material: {
                            color: [21, 227, 225, 0.3]
                        },
                        edges: {
                            type: 'solid',
                            color: '#4d5b18',
                            size: 1,
                        }
                    }]
                };
            }
            self.prop._graphicsLayer.addMany(features);
        });
    },

    checkWarningBuilding() {
        const self = this;
        const features = self.prop._areaFeatures;
        const field = self.prop._field;
        const queryPromiseAC = [];

        // 查询每个控制面范围中是否有建筑物
        for (let i = 0; i < features.length; i++) {
            queryPromiseAC.push(self.queryBuildings(features[i], field));
        }

        // 统一查询完毕之后，根据各个控制面以及对应的建筑物的高度进行判断
        // 如果建筑物的高度超出控制面设定高度的就高亮该建筑物
        Promise.all(queryPromiseAC).then(resAC => {
            let warningBuildingInfos = [];
            for (let i = 0; i < resAC.length; i++) {
                let targetFeatures = resAC[i].features;
                let heightForJudgment = Number(features[i].attributes[field]);
                for (let j = 0; j < targetFeatures.length; j++) {
                    let target = targetFeatures[j];
                    if (heightForJudgment < Number(target.attributes["height"])) {
                        warningBuildingInfos.push(target.attributes);
                    }
                }
            }
            self.highlightWarningBuilding(warningBuildingInfos);
        }).catch(console.error);
    },

    queryBuildings(feature) {
        const queryTask = new this.prop.QueryTask({
            url: this.prop._buildingAreaServerUrl
        });
        const query = new this.prop.Query();
        query.geometry = feature.geometry;
        query.outFields = ["objectid", "height"];
        query.returnGeometry = false;
        return queryTask.execute(query);
    },

    highlightWarningBuilding(warningBuildingInfos) {
        const uniqueValueInfos = warningBuildingInfos.map(attributes => {
            return {
                value: attributes["objectid"],
                symbol: {
                    type: "mesh-3d",
                    symbolLayers: [
                        {
                            type: "fill",
                            material: {
                                color: "red"
                            },
                            edges: {
                                type: 'solid',
                                color: 'red',
                                size: 1,
                            }
                        }
                    ]
                }
            };
        });

        const renderer = {
            type: "unique-value",
            field: "objectid",
            defaultSymbol: {
                type: "mesh-3d",
                symbolLayers: [
                    {
                        type: "fill",
                        material: {
                            color: "#ffffff",
                            colorMixMode: "replace"
                        }
                    }
                ]
            },
            uniqueValueInfos: uniqueValueInfos
        };

        const buildingSceneLayerTitle = this.prop._buildingSceneLayerTitle;
        const sceneLayer = this.prop._webScene.layers.find(function (ly) {
            return ly.title === buildingSceneLayerTitle;
        });
        sceneLayer.renderer = renderer;
    },

    resetBuildingRender() {
        const buildingSceneLayerTitle = this.prop._buildingSceneLayerTitle;
        const sceneLayer = this.prop._webScene.layers.find(function (ly) {
            return ly.title === buildingSceneLayerTitle;
        });
        sceneLayer.renderer = null;
    },

    addSpecialFeature(graphic) {
        const self = this;
        let heightForJudgment = -1;
        if (graphic.symbol) {
            graphic.watch("symbol", (newValue, oldValue) => {
                self.setOwnSymbol(graphic, newValue, oldValue);
                self.showIpt(newValue.symbolLayers.items[0].height);
            });
        }
        if (graphic.geometry) {
            // 根据要素与地块之间的相交关系，查询和设置该要素的控高标准值
            heightForJudgment = self.getHeightForJudgment(graphic.geometry);
            graphic.watch("geometry", (newValue, oldValue) => {
                self.setOwnHeightForJudgment(graphic, newValue, oldValue);
            });
        }

        self.prop._specialFeatures.push(graphic);
        self.prop._heightForJudgmentAC.push(heightForJudgment);

        self.prop._selectedGra = graphic;
        /** 
         * 下面的代码不需要了，放在gltf加载完成的回调函数 gltfDataReady 中进行同样的操作
        */
        // self.showIpt(graphic.symbol.symbolLayers.items[0].height);
        // 第一次手动做一次检测，如果默认设置高度超过控高盒子就能检测出来
        // self.setOwnSymbol(graphic, graphic.symbol, null);
    },

    getHeightForJudgment(geometry) {
        let result = -1;
        const features = this.prop._areaFeatures;
        const geometryEngine = this.prop.geometryEngine;
        for (let i = 0; i < features.length; i++) {
            if (geometryEngine.intersects(geometry, features[i].geometry)) {
                result = features[i].attributes[this.prop._field];
                break;
            }
        }
        return result;
    },

    setOwnHeightForJudgment(graphic, newGeometry, oldGeometry) {
        if (newGeometry.x != oldGeometry.x || newGeometry.y != oldGeometry.y) {
            let heightForJudgment = this.getHeightForJudgment(graphic.geometry);
            const targetIndex = this.prop._specialFeatures.indexOf(graphic);
            this.prop._heightForJudgmentAC[targetIndex] = heightForJudgment;
            this.setOwnSymbol(graphic, graphic.symbol, null);
        }
    },

    setOwnSymbol(graphic, newSymbol, oldSymbol) {
        const targetIndex = this.prop._specialFeatures.indexOf(graphic);
        const heightForJudgment = this.prop._heightForJudgmentAC[targetIndex];
        const curSymbolLayerObj = newSymbol.symbolLayers.items[0];
        if (heightForJudgment < 0) {
            // 没有控高盒子
            if (curSymbolLayerObj.material) {
                // console.log("还原了");
                graphic.symbol = this.getDefaultSymbol(curSymbolLayerObj);
            }
        } else {
            // const curHeight = realHeight ? realHeight : curSymbolLayerObj.height;
            const curHeight = curSymbolLayerObj.height;
            const oldHeight = oldSymbol ? oldSymbol.symbolLayers.items[0].height : undefined;
            // 为了达到只有高度变化才进行判断渲染，减少多余操作
            // 所以下面需要做多几个判断，确保两次symbol变化中，只有高度属性有变化，才进入判断渲染处理
            if (curHeight != oldHeight) {
                if (curHeight && heightForJudgment < curHeight) {
                    const material = curSymbolLayerObj.material;
                    if (!material || !(material.color.a == 1 && material.color.b == 0 && material.color.g == 0 && material.color.r == 255)) {
                        // console.log("高亮了");
                        // debugger
                        graphic.symbol = this.getHighLightSymbol(curSymbolLayerObj);
                    }
                } else {
                    if (curSymbolLayerObj.material) {
                        // console.log("还原了");
                        graphic.symbol = this.getDefaultSymbol(curSymbolLayerObj);
                    }
                }
            }
        }
    },

    getHighLightSymbol(symbolLayerObj) {
        const newSymbolLayerObj = symbolLayerObj.toJSON();
        newSymbolLayerObj.type = "object";// 转换出来会变Object，O变大写了，所以重新赋值一下
        newSymbolLayerObj.material = {
            color: "red"
        };
        return {
            type: "point-3d",
            symbolLayers: [newSymbolLayerObj]
        };
    },

    getDefaultSymbol(symbolLayerObj) {
        const newSymbolLayerObj = symbolLayerObj.toJSON();
        newSymbolLayerObj.type = "object";// 转换出来会变"Object"，O变大写了，所以重新赋值一下
        delete newSymbolLayerObj.material;
        return {
            type: "point-3d",
            symbolLayers: [newSymbolLayerObj]
        };
    },

    removeSpecialFeature(index) {
        this.prop._specialFeatures.splice(index, 1);
        this.prop._heightForJudgmentAC.splice(index, 1);
    },

    setHeightToIpt(event) {
        const self = this;
        const view = self.prop._view;
        self.prop._selectedGra = null;
        view.hitTest(event).then(response => {
            if (response.results.length) {
                const results = response.results;
                const specialFeatures = self.prop._specialFeatures;
                let flag = false;
                let targetGra = null;
                for (let i = 0; i < results.length; i++) {
                    if (flag == false) {
                        let resGra = results[i].graphic;
                        for (let j = 0; j < specialFeatures.length; j++) {
                            if (resGra.uid == specialFeatures[j].uid) {
                                flag = true;
                                targetGra = resGra;
                                break;
                            }
                        }
                    }
                }
                if (flag == true) {
                    self.prop._selectedGra = targetGra;
                    self.showIpt(targetGra.symbol.symbolLayers.items[0].height);
                } else {
                    self.hideIpt();
                }
            } else {
                self.hideIpt();
            }
        });
    },

    showIpt(value) {
        document.getElementById("attrHeightIpt").value = value;
        document.getElementById("attrCtrBox").style.display = "block";
    },

    hideIpt() {
        document.getElementById("attrCtrBox").style.display = "none";
    },

    changeBuildingHeight(event) {
        const self = this;
        const targetGra = self.prop._selectedGra;
        if (targetGra) {
            const targetIndex = self.prop._specialFeatures.indexOf(targetGra);
            const height = event.currentTarget.value;
            const heightForJudgment = self.prop._heightForJudgmentAC[targetIndex];
            const curSymbolLayerObj = targetGra.symbol.symbolLayers.items[0];
            let newSymbol = null;
            if (height > heightForJudgment) {
                newSymbol = self.getHighLightSymbol(curSymbolLayerObj);
            } else {
                newSymbol = self.getDefaultSymbol(curSymbolLayerObj);
            }
            newSymbol.symbolLayers[0].height = height;
            targetGra.symbol = newSymbol;
            // console.log("更新高度数值了");
        }
    },

    gltfDataReady(symbolSize) {
        // console.log(symbolSize);
        document.getElementById("loadingBox").style.display = "none";
        const realWidth = symbolSize[0];
        const realHeight = symbolSize[2];
        const graphic = this.prop._selectedGra;
        this.showIpt(realHeight);
        // 判断是否有设置默认高度，如果没有则取模型的高度作为默认高度并赋值
        if (!graphic.symbol.symbolLayers.items[0].height && graphic.symbol.symbolLayers.items[0].height != 0) {
            graphic.symbol.symbolLayers.items[0].height = realHeight;
        }
        // 判断是否有设置默认宽度，如果没有则取模型的宽度作为默认高度并赋值
        if (!graphic.symbol.symbolLayers.items[0].width && graphic.symbol.symbolLayers.items[0].width != 0) {
            graphic.symbol.symbolLayers.items[0].width = realWidth;
        }
        // 首次加载默认进行一次高度检测
        this.setOwnSymbol(graphic, graphic.symbol, null);
    }
};